From: Keir Fraser Date: Mon, 13 Jul 2009 10:52:49 +0000 (+0100) Subject: VT-d: fix assertion fault in pci passthrough code X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13612 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=fbaf0db4fc12f64072d81576de944e87f23714c7;p=xen.git VT-d: fix assertion fault in pci passthrough code Remove ASSERT(spin_is_locked(&pcidevs_lock)) in pci_get_pdev_by_domain() to allow caller the flexibility to not hold the lock if it does not care if the device is hot removed between the time it got the pdev and the time it is used to get the corresponding vt-d engine. In the new RHSA use case, we just wanted to get the vt-d engine of any device passthrough in the domain. Also, rename RHSA field "domain" to "proximity domain" to avoid overloading the term "domain" in virtualization context. Signed-off-by: Allen Kay --- diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index 0327114fef..27699e038b 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -89,8 +89,6 @@ struct pci_dev *pci_get_pdev_by_domain(struct domain *d, int bus, int devfn) { struct pci_dev *pdev = NULL; - ASSERT(spin_is_locked(&pcidevs_lock)); - list_for_each_entry ( pdev, &alldevs_list, alldevs_list ) if ( (pdev->bus == bus || bus == -1) && (pdev->devfn == devfn || devfn == -1) && diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 0912c97ff0..fbbc30204f 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -499,7 +499,7 @@ acpi_parse_one_rhsa(struct acpi_dmar_entry_header *header) memset(rhsau, 0, sizeof(struct acpi_rhsa_unit)); rhsau->address = rhsa->address; - rhsau->domain = rhsa->domain; + rhsau->proximity_domain = rhsa->proximity_domain; list_add_tail(&rhsau->list, &acpi_rhsa_units); return ret; diff --git a/xen/drivers/passthrough/vtd/dmar.h b/xen/drivers/passthrough/vtd/dmar.h index 5f78a95f94..bed177adc6 100644 --- a/xen/drivers/passthrough/vtd/dmar.h +++ b/xen/drivers/passthrough/vtd/dmar.h @@ -72,7 +72,7 @@ struct acpi_atsr_unit { struct acpi_rhsa_unit { struct list_head list; u64 address; - u32 domain; + u32 proximity_domain; }; #define for_each_drhd_unit(drhd) \ diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index a0cf9d12d7..608865612d 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -143,10 +143,14 @@ u64 alloc_pgtable_maddr(struct acpi_drhd_unit *drhd, unsigned long npages) struct acpi_rhsa_unit *rhsa; struct page_info *pg; u64 *vaddr; + int node = -1; rhsa = drhd_to_rhsa(drhd); + if ( rhsa ) + node = pxm_to_node(rhsa->proximity_domain); + pg = alloc_domheap_pages(NULL, get_order_from_pages(npages), - rhsa ? rhsa->domain : 0); + (node == -1 ) ? 0 : MEMF_node(node)); if ( !pg ) return 0; vaddr = map_domain_page(page_to_mfn(pg)); @@ -204,6 +208,10 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc) ASSERT(spin_is_locked(&hd->mapping_lock)); if ( hd->pgd_maddr == 0 ) { + /* + * just get any passthrough device in the domainr - assume user + * assigns only devices from same node to a given guest. + */ pdev = pci_get_pdev_by_domain(domain, -1, -1); drhd = acpi_find_matched_drhd_unit(pdev); if ( !alloc || ((hd->pgd_maddr = alloc_pgtable_maddr(drhd, 1)) == 0) ) diff --git a/xen/include/xen/acpi.h b/xen/include/xen/acpi.h index 1023d8106d..a56d27048f 100644 --- a/xen/include/xen/acpi.h +++ b/xen/include/xen/acpi.h @@ -227,7 +227,7 @@ struct acpi_table_atsr { struct acpi_table_rhsa { struct acpi_dmar_entry_header header; - u32 domain; + u32 proximity_domain; u64 address; /* register base address for this drhd */ } __attribute__ ((packed));